package com.netty.junjie.socket.decoder;

import com.netty.junjie.socket.entity.ConversionData;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

import static com.netty.junjie.common.ByteUtils.encodeHexStr;
import static com.netty.junjie.constant.ConstantBytes.*;

/**
 * *
 * ConversionDecoder 解码器
 *
 * @author JunJie
 * @Date 2020/07/13 07:13
 **/
@Slf4j
public class ConversionDecoder extends ByteToMessageDecoder {

    /**
     * 数据域字节数
     */
    private static int dataFieldBytes = 0;

    /**
     * 数据域分组数
     */
    private static int dataFieldGroups = 0;

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out) {
        log.debug("<<<<===============解码开始===============>>>>");

        byte[] writerIndexByte = new byte[in.writerIndex()];
        in.readBytes(writerIndexByte);
        log.debug("数据包为 :" + encodeHexStr(writerIndexByte));

        //重置可读索引
        in.readerIndex(0);

        int writerIndex = in.writerIndex();
        //可读字节数 < 最小字节数  可读字节不是 2 的倍数 false 抛出异常
        if (writerIndex < BYTE_MIN_NUMBER || writerIndex % DIVIDE_BY_NUMBER != 0) {
            throw new IndexOutOfBoundsException();
        }
        try {
            ConversionData conversionData = new ConversionData();
            // 包头标示
            byte[] baotouLogo = new byte[PACKET_HEADER_BYTES];
            in.readBytes(baotouLogo);
            conversionData.setBaotouLogo(baotouLogo);
            log.debug("包头标示: " + encodeHexStr(baotouLogo));

            // 数据长度
            byte[] dataLength = new byte[DATA_LENGTH];
            in.readBytes(dataLength);
            conversionData.setDataLength(dataLength);
            log.debug("数据长度: " + encodeHexStr(dataLength));

            // 客户端IP地址
            byte[] clientIPAddress = new byte[CLIENT_ADDRESS];
            in.readBytes(clientIPAddress);
            conversionData.setClientIPAddress(clientIPAddress);
            log.debug("客户端IP地址: " + encodeHexStr(clientIPAddress));

            // 服务器IP地址
            byte[] serverIPAddress = new byte[SERVER_ADDRESS];
            in.readBytes(serverIPAddress);
            conversionData.setServerIPAddress(serverIPAddress);
            log.debug("服务器IP地址: " + encodeHexStr(serverIPAddress));

            // 协议版本号
            byte[] agreementVersionNumber = new byte[AGREEMENT_VERSION];
            in.readBytes(agreementVersionNumber);
            conversionData.setAgreementVersionNumber(agreementVersionNumber);
            log.debug("协议版本号: " + encodeHexStr(agreementVersionNumber));

            // 数据类型
            byte[] dataType = new byte[DATA_TYPE];
            in.readBytes(dataType);
            conversionData.setDataType(dataType);
            log.debug("数据类型: " + encodeHexStr(dataType));

            // 包序号
            byte[] packageNumber = new byte[PACKAGE_NUMBER];
            in.readBytes(packageNumber);
            conversionData.setPackageNumber(packageNumber);
            log.debug("包序号: " + encodeHexStr(packageNumber));

            // 系统时间
            byte[] systemTime = new byte[SYSTEM_TIME];
            in.readBytes(systemTime);
            conversionData.setSystemTime(systemTime);
            log.debug("系统时间: " + encodeHexStr(systemTime));

            // 发送端的MAC地址
            byte[] macAddress = new byte[MAC_ADDRESS];
            in.readBytes(macAddress);
            conversionData.setMacAddress(macAddress);
            log.debug("发送端的MAC地址: " + encodeHexStr(macAddress));

            // 预留位
            byte[] reserved = new byte[RESERVED];
            in.readBytes(reserved);
            conversionData.setReserved(reserved);
            log.debug("预留位: " + encodeHexStr(reserved));

            //可读字节数 - 已读字节数 - 校验位 - 包结束位 (4是校验位和包结束位的字节数)
            int num = in.writerIndex() - in.readerIndex() - CHECK_BIT - PACKET_END_BIT;
            if (num == DATA_FIELD) {
                dataFieldGroups = 1;
                dataFieldBytes = num;
            }
            //数据域字节数小于12 不给予解码
            if (num < DATA_FIELD && num % DIVIDE_BY_NUMBER == 0) {
                throw new IndexOutOfBoundsException();
            }
            if (num > DATA_FIELD && num % DIVIDE_BY_NUMBER == 0) {
                dataFieldGroups = num / DATA_FIELD;
                dataFieldBytes = num;
            }

            conversionData.setBytesNumber(dataFieldBytes);
            conversionData.setGroupNumber(dataFieldGroups);

            // 数据域 字节解析  可读取字节- 4(4是校验位和包结束位的字节数)
            byte[] dataBytes = new byte[num];
            in.readBytes(dataBytes);
            conversionData.setDataBytes(dataBytes);
            log.debug("数据域: " + encodeHexStr(dataBytes));

            // 校验位
            byte[] checkBit = new byte[CHECK_BIT];
            in.readBytes(checkBit);
            conversionData.setCheckBit(checkBit);
            log.debug("校验位: " + encodeHexStr(checkBit));

            // 包结束位
            byte[] packetEndBit = new byte[PACKET_END_BIT];
            in.readBytes(packetEndBit);
            conversionData.setPacketEndBit(packetEndBit);
            log.debug("包结束位: " + encodeHexStr(packetEndBit));
            log.debug("<<<<===============解码结束===============>>>>");
            out.add(conversionData);
        } catch (Exception e) {
            log.error("<<<<===============解码异常===============>>>>");
            throw new IndexOutOfBoundsException();
        }
    }
}
